/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using EvaluationException = System.Qizx.Api.EvaluationException;
using Item = System.Qizx.Api.Item;
using ArraySequence = System.Qizx.XQuery.Dt.ArraySequence;
using ErrorValue = System.Qizx.XQuery.Impl.ErrorValue;
namespace System.Qizx.XQuery {

    /// <summary> Internal representation of the result of the evaluation of a query, which is
    /// a sequence of Items (IItem). This interface generally cannot be used for
    /// remote access.
    /// <para>
    /// The next() method must be repeatedly invoked to check whether an item is
    /// available.</para>
    /// <para>
    /// When next() returns true, the current item value can be retrieved by
    /// specialized methods getX() (defined in super-interface XQItem) according to
    /// its type.</para>
    /// <para>
    /// Value has often the dual aspect of a sequence and an Item. It is not
    /// immutable, because of the next() method. It cannot be rewinded, but it can
    /// be regenerated by bornAgain().</para>
    /// </summary>
    public struct XQValues {
        // ---------------- special values -------------------------------------

        public readonly static XQValue Empty;
        public readonly static XQValue TOO_SHORT;
        public readonly static XQValue TOO_LONG;
        static XQValues() {
            Empty = new AnonymousClassArraySequence(null, 0);
            TOO_SHORT = new ErrorValue(XQType.ERR_EMPTY_UNEXPECTED);
            TOO_LONG = new ErrorValue(XQType.ERR_TOO_MANY);
        }
    }
    internal class AnonymousClassArraySequence : ArraySequence {
        internal AnonymousClassArraySequence(System.Object[] Param1, int Param2)
            : base(Param1, Param2) {
        }
        public override XQValue BornAgain() {
            return this;
        }
    }
    public interface XQValue : XQItem {
        /// <summary> Gets the current item (undefined result if end of sequence reached).</summary>
        XQItem Item {
            get;

        }
        /// <summary> Boosts iterations that dont need the item value (count(), skipping)</summary>
        bool Lazy {
            set;

        }
        /// <summary> Attempts to get the next atomic item. If true is returned, the item
        /// value is available through one of the specialized accessors.
        /// </summary>
        bool Next();

        /// <summary> Attempts to get the next atomic item, without expanding collections.</summary>
        bool NextCollection();

        /// <summary> Returns the full-text score of the specified item (or the current item
        /// if null is passed).
        /// If the sequence does not involve a full-text query,
        /// then return a negative value, otherwise a value between 0 and 1.
        /// </summary>
        /// <param name="item">if null, use the current item of this sequence
        /// </param>
        /// <throws>  EvaluationException  </throws>
        double GetFulltextScore(Item item);

        /// <summary> Returns a new version of the sequence <i>in its initial state</i>.
        /// Value objects are in principle immutable, but due to the iterative
        /// implementation style (see the {@link #next()} method), this is not
        /// actually true. Therefore when a value is used several times (in
        /// particular the value of a variable), there is a need for "regeneration".
        /// <p>
        /// NOTE: this needs not be a deep copy, because only the state of the
        /// iterator is concerned, not the underlying data.
        /// </summary>
        XQValue BornAgain();

        void Close();

        /// <summary> Expansion of a sequence with type-checking. Returns an ArraySequence.
        /// Both the item types and the length of the sequence are checked. May be
        /// redefined by a few implementations (IntRange) to avoid actually building
        /// a sequence.
        /// 
        /// </summary>
        /// <param name="type">sequence type: may be null.
        /// </param>
        /// <param name="conversion">if true, conversion of nodes to untypedAtomic and cast
        /// (or promotion) are allowed: used for function parameters and
        /// result.
        /// </param>
        /// <param name="build">if false, dont build a result sequence (simple test)
        /// </param>
        /// <returns> if OK, the expanded sequence, with possible conversions if
        /// 'conversion' is true, or null if build is false. If not OK,
        /// return special values TOO_SHORT, TOO_LONG, or match error (Spe
        /// </returns>
        /// <throws>  EvaluationException </throws>
        XQValue CheckTypeExpand(XQType type, EvalContext context, bool conversion, bool build);

        /// <summary> Returns false if it is more efficient to keep the value as an iterator,
        /// and not to expand it into an array sequence. This method is used when a
        /// value is stored into variable. It should return false only when the
        /// value is cheap to compute AND doesnt involve Node constructors (because
        /// of a problem with Node identity).
        /// </summary>
        bool WorthExpanding();

        /// <summary> Optimized evaluation of count() or last(). Assumes the iterator to be in
        /// initial state.
        /// 
        /// </summary>
        /// <param name="context">evaluation context: used for monitoring.
        /// </param>
        long QuickCount(EvalContext context);

        /// <summary> Repetition of next().</summary>
        int DoSkip(int count);

        /// <summary> Optimized evaluation of operator [] with integer $index.</summary>
        XQItem QuickIndex(long index);

        /// <summary> Check whether quick indexing is supported.</summary>
        bool HasQuickIndex();

    }
}